﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;

namespace Tenancy.wxpay.lib
{
    public class WxPayApi
    {
        public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 60)
        {
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            //检测必填参数
            //if (!inputObj.IsSet("out_trade_no"))
            //{
            //    throw new WxPayException("缺少统一支付接口必填参数out_trade_no！");
            //}
            //else if (!inputObj.IsSet("body"))
            //{
            //    throw new WxPayException("缺少统一支付接口必填参数body！");
            //}
            //else if (!inputObj.IsSet("total_fee"))
            //{
            //    throw new WxPayException("缺少统一支付接口必填参数total_fee！");
            //}
            //else if (!inputObj.IsSet("spbill_create_ip"))
            //{
            //    throw new WxPayException("缺少统一支付接口必填参数spbill_create_ip！");
            //}

            //else if (!inputObj.IsSet("trade_type"))
            //{
            //    throw new WxPayException("缺少统一支付接口必填参数trade_type！");
            //}




            //异步通知url未设置，则使用配置文件中的url
            if (!inputObj.IsSet("notify_url"))
            {
                inputObj.SetValue("notify_url", WxPayConfig.NOTIFY_URL);//异步通知url
            }



            string xml = inputObj.ToXml();


            var start = DateTime.Now;

            Log.Debug("WxPayApi", "UnfiedOrder request : " + xml);
            string response = HttpService.Post(xml, url, false, timeOut);
            Log.Debug("WxPayApi", "UnfiedOrder response : " + response);

            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);

            WxPayData result = new WxPayData();
            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//测速上报

            return result;
        }

        /**
     * 生成随机串，随机串包含字母或数字
     * @return 随机串
     */
        public static string GenerateNonceStr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }

        /**
      * 
      * 测速上报
      * @param string interface_url 接口URL
      * @param int timeCost 接口耗时
      * @param WxPayData inputObj参数数组
      */
        private static void ReportCostTime(string interface_url, int timeCost, WxPayData inputObj)
        {
            //如果不需要进行上报
            if (WxPayConfig.REPORT_LEVENL == 0)
            {
                return;
            }

            //如果仅失败上报
            if (WxPayConfig.REPORT_LEVENL == 1 && inputObj.IsSet("return_code") && inputObj.GetValue("return_code").ToString() == "SUCCESS" &&
             inputObj.IsSet("result_code") && inputObj.GetValue("result_code").ToString() == "SUCCESS")
            {
                return;
            }

            //上报逻辑
            WxPayData data = new WxPayData();
            data.SetValue("interface_url", interface_url);
            data.SetValue("execute_time_", timeCost);
            //返回状态码
            if (inputObj.IsSet("return_code"))
            {
                data.SetValue("return_code", inputObj.GetValue("return_code"));
            }
            //返回信息
            if (inputObj.IsSet("return_msg"))
            {
                data.SetValue("return_msg", inputObj.GetValue("return_msg"));
            }
            //业务结果
            if (inputObj.IsSet("result_code"))
            {
                data.SetValue("result_code", inputObj.GetValue("result_code"));
            }
            //错误代码
            if (inputObj.IsSet("err_code"))
            {
                data.SetValue("err_code", inputObj.GetValue("err_code"));
            }
            //错误代码描述
            if (inputObj.IsSet("err_code_des"))
            {
                data.SetValue("err_code_des", inputObj.GetValue("err_code_des"));
            }
            //商户订单号
            if (inputObj.IsSet("out_trade_no"))
            {
                data.SetValue("out_trade_no", inputObj.GetValue("out_trade_no"));
            }
            //设备号
            if (inputObj.IsSet("device_info"))
            {
                data.SetValue("device_info", inputObj.GetValue("device_info"));
            }

            try
            {
                Report(data);
            }
            catch (WxPayException ex)
            {
                //不做任何处理
            }
        }

        /**
      * 
      * 测速上报接口实现
      * @param WxPayData inputObj 提交给测速上报接口的参数
      * @param int timeOut 测速上报接口超时时间
      * @throws WxPayException
      * @return 成功时返回测速上报接口返回的结果，其他抛异常
      */
        public static WxPayData Report(WxPayData inputObj, int timeOut = 1)
        {
            string url = "https://api.mch.weixin.qq.com/payitil/report";
            //检测必填参数
            if (!inputObj.IsSet("interface_url"))
            {
                throw new WxPayException("接口URL，缺少必填参数interface_url！");
            }
            if (!inputObj.IsSet("return_code"))
            {
                throw new WxPayException("返回状态码，缺少必填参数return_code！");
            }
            if (!inputObj.IsSet("result_code"))
            {
                throw new WxPayException("业务结果，缺少必填参数result_code！");
            }
            if (!inputObj.IsSet("user_ip"))
            {
                throw new WxPayException("访问接口IP，缺少必填参数user_ip！");
            }
            if (!inputObj.IsSet("execute_time_"))
            {
                throw new WxPayException("接口耗时，缺少必填参数execute_time_！");
            }

            inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
            inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
            inputObj.SetValue("user_ip", WxPayConfig.IP);//终端ip
            inputObj.SetValue("time", DateTime.Now.ToString("yyyyMMddHHmmss"));//商户上报时间	 
            inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());//签名
            string xml = inputObj.ToXml();

            Log.Info("WxPayApi", "Report request : " + xml);

            string response = HttpService.Post(xml, url, false, timeOut);

            Log.Info("WxPayApi", "Report response : " + response);

            WxPayData result = new WxPayData();
            result.FromXml(response);
            return result;
        }


        /**
       *    
       * 查询订单
       * @param WxPayData inputObj 提交给查询订单API的参数
       * @param int timeOut 超时时间
       * @throws WxPayException
       * @return 成功时返回订单查询结果，其他抛异常
       */
        public static WxPayData OrderQuery(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/pay/orderquery";
            //检测必填参数
            if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
            {
                throw new WxPayException("订单查询接口中，out_trade_no、transaction_id至少填一个！");
            }

            inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
            inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
            inputObj.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());//签名

            string xml = inputObj.ToXml();

            var start = DateTime.Now;

            Log.Debug("WxPayApi", "OrderQuery request : " + xml);
            string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口提交数据
            Log.Debug("WxPayApi", "OrderQuery response : " + response);

            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时

            //将xml格式的数据转化为对象以返回
            WxPayData result = new WxPayData();
            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//测速上报

            return result;
        }

        //退款
        public static WxPayData refundNew(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";


            inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
            inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
            inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
            inputObj.SetValue("op_user_id", "1316525101");
            inputObj.SetValue("out_refund_no", "1316525101201607091524498758");
            inputObj.SetValue("refund_fee", "10");
            inputObj.SetValue("total_fee", "10");
            inputObj.SetValue("transaction_id", "4008572001201607098645149499");
            inputObj.SetValue("sign", inputObj.MakeSign());//签名


            string xml = inputObj.ToXml();

            Log.Info("WxPayApi", "Report request : " + xml);

            string response = HttpService.Post(xml, url, true, timeOut);

            Log.Info("WxPayApi", "Report response : " + response);

            WxPayData result = new WxPayData();
            result.FromXml(response);
            return result;
        }


        //public static WxPayData refund(WxPayData inputObj, int timeOut = 60)
        //{
        //    string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";


        //    WxPayData result = null;
        //    string sql = "    SELECT transactionid,out_trade_no,total_fee FROM dbo.hb_WXJieSMessage  WHERE out_trade_no IN( SELECT ShopingNum FROM dbo.hb_order WHERE status=3 AND user_id=78 AND type IN(10,11,12,13)) ";
        //    DataTable dt = new DataTable();
        //    QueryCommand qc = new InlineQuery().GetCommand(sql);
        //    dt = DataService.GetDataSet(qc).Tables[0];
        //    if (dt.Rows.Count > 0)
        //    {
        //        for (int i = 0; i < dt.Rows.Count; i++)
        //        {
        //            inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
        //            inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
        //            inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
        //            inputObj.SetValue("op_user_id", "1316525101");
        //            inputObj.SetValue("out_refund_no", dt.Rows[i]["out_trade_no"]);
        //            inputObj.SetValue("refund_fee", Convert.ToInt32(dt.Rows[i]["total_fee"]));
        //            inputObj.SetValue("total_fee", Convert.ToInt32(dt.Rows[i]["total_fee"]));


        //            inputObj.SetValue("transaction_id", dt.Rows[i]["transactionid"]);
        //            inputObj.SetValue("sign", inputObj.MakeSign());//签名


        //            string xml = inputObj.ToXml();

        //            Log.Info("WxPayApi", "Report request : " + xml);

        //            string response = HttpService.Post(xml, url, true, timeOut);

        //            Log.Info("WxPayApi", "Report response : " + response);

        //             result = new WxPayData();
        //            result.FromXml(response);
        //        }
        //    }


        //    return result;
        //}

        /**
      * 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
       * @return 时间戳
      */
        public static string GenerateTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /**
       * 根据当前系统时间加随机序列来生成订单号
        * @return 订单号
       */
        public static string GenerateOutTradeNo()
        {
            var ran = new Random();
            return string.Format("{0}{1}{2}", WxPayConfig.MCHID, DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(9999));
        }

    }
}